home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Reference Guide
/
C-C++ Interactive Reference Guide.iso
/
c_ref
/
csource1
/
bootsec
/
bootsec.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-08
|
25KB
|
662 lines
//****************************************************************************
// File: BOOTSEC.C
//
//
// Purpose: The main module. Brings up a private dialog, that prompts
// the user for a drive letter. When the user chooses "Get
// Info", BOOTSEC determines what kind of drive it is, and then if
// appropriate, reads the boot sector of the drive, and displays
// all the information from the bootsector in the dialog.
//
// Functions:
// WinMain() - initializes app and processes message loop
// ActualDlgProc - the actual Dialog Procedure
// AboutDlgProc - Dialog procedure for the About box
// ClassDlgProc - the Window Proc for the Private Dialog
// NewEditProc - the subclassed Edit window procedure
// ReadBootSector - read the boot sector via INT 25
// ShowDriveInfo - display the boot sector structure
// GetPictRect - get a rect to display a drive icon
// IsCDRomDrive - is it a CD-ROM drive?
// IsNetDrive - is it a network drive?
// SetAllLabels - show a given string in all the labels
// MyGetDriveType - return the type of drive
//
// Development Team:
//
// Joe Long, June 1993
//
//
// Written by Microsoft Product Support Services, Windows Developer Support
// Copyright (c) 1992 Microsoft Corporation. All rights reserved.
//****************************************************************************
#include "windows.h"
#include "bootsec.h"
#include "memory.h"
#include "resource.h"
#define CBSECTORSIZE 512
// global vars
int iDriveType; // what kind of drive is selected
HINSTANCE hInst; // the instance handle
FARPROC lpfnOldEditProc; // the original edit procedure
char szErrorBuf[64]; // a buffer to load error strings
// exported function
int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
BOOL FAR PASCAL __export ActualDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
BOOL FAR PASCAL __export AboutDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
long FAR PASCAL __export ClassDlgProc(HWND hDlg, UINT message, WPARAM wParam , LPARAM lParam);
long FAR PASCAL __export NewEditProc(HWND hEdit, UINT message, WPARAM wParam , LPARAM lParam);
//helper functions
BOOL ReadBootSector(int iDrive, PSTR pBuf);
void ShowDriveInfo(HWND hDlg, BOOTSECTOR *bs);
void GetPictRect(HWND hWnd, LPRECT lpRect);
BOOL IsCDRomDrive(int iDrive);
WORD IsNetDrive(int iDrive);
void SetAllLabels(HWND hDlg, LPSTR szText);
int MyGetDriveType(BOOTSECTOR *bs);
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
WNDCLASS wc;
HWND hwnd;
DLGPROC dlgProc;
hInst = hInstance;
if (!hPrevInstance)
{
memset(&wc,NULL, sizeof(WNDCLASS));
wc.lpfnWndProc = ClassDlgProc;
wc.cbWndExtra = DLGWINDOWEXTRA;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_MAIN));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = COLOR_WINDOW + 1;
wc.lpszClassName = "BootSectorClass";
RegisterClass(&wc);
}
dlgProc = (DLGPROC)MakeProcInstance(ActualDlgProc, hInst);
hwnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_MAINDIALOG), 0, dlgProc);
ShowWindow(hwnd,nCmdShow);
while (GetMessage(&msg,NULL,0,0))
{
// if we want to be able to use the TAB key
// to move between controls, the ENTER
// key to execute the default button,
// the ESCAPE key to dismiss the dialog,
// or any other dialog - type functionality,
// we must call IsDialogMessage()
if (!IsDialogMessage(hwnd, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
FreeProcInstance((FARPROC)dlgProc);
return msg.wParam;
}
/****************************************************************************
ClassDlgProc(HWND hDlg, UINT message, WPARAM wParam , LPARAM lParam)
PURPOSE:
this function gets placed between the dialog and the DefDlgProc because
1. its a private dialog
and
2. we specified a DLGPROC for the third parameter
of the CreateDialog() call.
we could handle all of the messages here (except for the WM_INITDIALOG
message which is not sent to non-dialogs, or we can pass the messages
off to DefDlgProc(), which will then call our dialog procedure
ActualDlgProc(), given below
****************************************************************************/
long FAR PASCAL __export ClassDlgProc(HWND hDlg, UINT message, WPARAM wParam , LPARAM lParam)
{
return DefDlgProc(hDlg, message, wParam, lParam);
}
/****************************************************************************
ActualDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
PURPOSE:
The procedure for the application that does most of the work.
This is the function that we passed in as the last parameter to the
CreateDialog() call. We do this so that we can get the WM_INITDIALOG
message, which is not passed to the WndProc of a Private Dialog.
We subclass the edit control so that we can restrict input to capital
letters, the backspace key, and the TAB key.
****************************************************************************/
BOOL FAR PASCAL __export ActualDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
static HDC hMemDC;
static HBITMAP hBitmap, hbmOld;
switch (message)
{
case WM_INITDIALOG:
{
HDC hdc;
HWND hwndEdit;
HMENU hSysMenu;
hSysMenu = GetSystemMenu(hDlg, FALSE);
// disable the "maximize" option in the system menu
EnableMenuItem(hSysMenu, 4, MF_GRAYED|MF_DISABLED|MF_BYPOSITION);
// disable the "size" option of the system menu
EnableMenuItem(hSysMenu, 2, MF_GRAYED|MF_DISABLED|MF_BYPOSITION);
// subclass the edit control so that we
// can restrict input to letter only
hwndEdit = GetDlgItem(hDlg, IDC_DRIVE);
if (hwndEdit)
lpfnOldEditProc = (FARPROC)SetWindowLong(hwndEdit, GWL_WNDPROC, (LONG)NewEditProc);
// limit the text of the edit control to 1 character
SendMessage(hwndEdit, EM_LIMITTEXT, 1, 0L);
// put a reasonable default into the edit control
SetWindowText(hwndEdit, "C");
hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_DRIVES));
hdc = GetDC(NULL);
hMemDC = CreateCompatibleDC(hdc);
ReleaseDC(NULL, hdc);
hbmOld = SelectObject(hMemDC, hBitmap);
iDriveType = BM_NONE;
return FALSE; // didn't set the focus
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rect;
BeginPaint(hDlg, &ps);
GetPictRect(hDlg, &rect);
BitBlt(ps.hdc,rect.left, rect.top,
BM_WIDTH, BM_HEIGHT,
hMemDC,
iDriveType * BM_WIDTH,
0,
SRCCOPY);
EndPaint(hDlg, &ps);
}
break;
case WM_COMMAND:
switch (wParam)
{
case ID_ABOUT:
{
DLGPROC dlgprc;
dlgprc = (DLGPROC) MakeProcInstance(AboutDlgProc, hInst);
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT), hDlg, dlgprc);
FreeProcInstance((FARPROC) dlgprc);
}
break;
case ID_GET:
{
int iDrive;
char szDrive[2];
BOOTSECTOR *bs;
char szBuffer[512];
RECT rect;
BOOL bRet;
// get the rectangle for the bitmap
GetPictRect(hDlg, &rect);
InvalidateRect(hDlg, &rect, TRUE);
// set the focus to the edit control
SetFocus(GetDlgItem(hDlg, IDC_DRIVE));
// hilite the text in the edit control
SendDlgItemMessage(hDlg, IDC_DRIVE, EM_SETSEL,0,MAKELPARAM(0,-1));
GetDlgItemText(hDlg, IDC_DRIVE, szDrive, 2);
iDrive = szDrive[0] - 'A';
if (IsCDRomDrive(iDrive))
{
LoadString(hInst, IDS_NOCDROM, szErrorBuf, sizeof(szErrorBuf));
iDriveType = BM_CDROM;
// if the MessageBox has no caption, Windows
// will put "Error" as the caption, so we can
// save some space by leaving it off...
MessageBox(hDlg, szErrorBuf, "", MB_ICONSTOP|MB_OK);
SetAllLabels(hDlg, "N/A");
UpdateWindow(hDlg);
break;
}
if (IsNetDrive(iDrive))
{
LoadString(hInst, IDS_NONET, szErrorBuf, sizeof(szErrorBuf));
iDriveType = BM_NET;
MessageBox(hDlg, szErrorBuf, "", MB_ICONSTOP|MB_OK);
SetAllLabels(hDlg, "N/A");
UpdateWindow(hDlg);
break;
}
SetCapture(hDlg);
SetCursor(LoadCursor(NULL, IDC_WAIT));
bRet = ReadBootSector(iDrive, szBuffer);
ReleaseCapture();
SetCursor(LoadCursor(NULL, IDC_ARROW));
if (bRet)
{
int nDriveType;
bs = (BOOTSECTOR *)szBuffer;
ShowDriveInfo(hDlg, bs);
nDriveType = MyGetDriveType(bs);
switch (nDriveType)
{
case DRIVE_REMOVABLE:
iDriveType = BM_FLOPPY;
break;
case DRIVE_RAM:
iDriveType = BM_RAM;
break;
case DRIVE_FIXED:
iDriveType = BM_FIXED;
break;
default: // this should never happen!!
iDriveType = BM_NONE;
break;
}
}
else // failed to read boot sector!
{
LoadString(hInst, IDS_READERROR, szErrorBuf, sizeof(szErrorBuf));
iDriveType = BM_NONE;
MessageBox(hDlg, szErrorBuf, "", MB_ICONSTOP|MB_OK);
SetAllLabels(hDlg, "N/A");
UpdateWindow(hDlg);
}
}
break;
case IDCANCEL:
DestroyWindow(hDlg);
break;
default:
return FALSE; // didn't handle it
break;
}
break;
case WM_DESTROY:
SelectObject(hMemDC, hbmOld);
DeleteObject(hBitmap);
DeleteDC(hMemDC);
PostQuitMessage(0);
break;
default:
return FALSE; //didn't handle the message
break;
}
return TRUE; // we handled the message
}
/****************************************************************************
FUNCTION: ReadBootSector(int iDrive, PSTR pTemp)
PURPOSE: reads the boot sector of iDrive into the pTemp buffer.
pTemp should be at least 512 bytes
we use the #pragma to turn optimization off so that the compiler won't
complain about the inline assembly
****************************************************************************/
#pragma optimize("",off)
BOOL ReadBootSector(int iDrive, PSTR pTemp)
{
DISKIO dio;
NPDISKIO npDIO;
dio.diStartSector = 0;
dio.diSectors = 1;
dio.diBuffer = pTemp;
npDIO = &dio;
_asm
{
mov ax, iDrive /* Drive number (0 based) */
mov bx, npDIO /* Establish buffer for read */
mov cx, 0FFFFh /* use the DISKIO structure */
xor dx, dx /* ignored */
int 25h /* Absolute Disk Read */
jc error
popf // pop registers
}
return TRUE;
error:
return FALSE;
}
#pragma optimize("",on)
/****************************************************************************
FUNCTION: ShowDriveInfo(HWND hDlg, BOOTSECTOR *bs)
PURPOSE:
given a pointer to a BOOTSECTOR structure, display its
contents in the dialog. Its assumed that the id's of the
static controls start at ID_FIRST and are sequential to
ID_LAST, and are in the same order as the structure.
****************************************************************************/
void ShowDriveInfo(HWND hDlg, BOOTSECTOR *bs)
{
int iParameter,nCount;
char szBuf[64];
iParameter = ID_FIRST;
wsprintf((LPSTR)szBuf, "%#x",(WORD)bs -> bsJump);
SetDlgItemText(hDlg,iParameter++,szBuf);
wsprintf((LPSTR)szBuf, "%s",(LPSTR)bs -> bsOemName);
SetDlgItemText(hDlg,iParameter++,szBuf);
wsprintf((LPSTR)szBuf, "%d",(WORD)bs -> bsBytePerSec);
SetDlgItemText(hDlg,iParameter++,szBuf);
wsprintf((LPSTR)szBuf, "%d",(BYTE)bs -> bsSecPerCluster);
SetDlgItemText(hDlg,iParameter++,szBuf);
wsprintf((LPSTR)szBuf, "%d",(WORD)bs -> bsResSectores);
SetDlgItemText(hDlg,iParameter++,szBuf);
wsprintf((LPSTR)szBuf, "%d",(BYTE)bs -> bsFAT);
SetDlgItemText(hDlg,iParameter++,szBuf);
wsprintf((LPSTR)szBuf, "%d",(WORD)bs -> bsRootDirEnts);
SetDlgItemText(hDlg,iParameter++,szBuf);
wsprintf((LPSTR)szBuf, "%d",(WORD)bs -> bsSectors);
SetDlgItemText(hDlg,iParameter++,szBuf);
wsprintf((LPSTR)szBuf, "%#x",(BYTE)bs -> bsMedia);
SetDlgItemText(hDlg,iParameter++,szBuf);
wsprintf((LPSTR)szBuf, "%d",(WORD)bs -> bsFATsecs);
SetDlgItemText(hDlg,iParameter++,szBuf);
wsprintf((LPSTR)szBuf, "%d",(WORD)bs -> bsSecPerTrack);
SetDlgItemText(hDlg,iParameter++,szBuf);
wsprintf((LPSTR)szBuf, "%d",(WORD)bs -> bsHeads);
SetDlgItemText(hDlg,iParameter++,szBuf);
// if we have a RAM drive (only one FAT), then
// all the following information is invalid
if (MyGetDriveType(bs) != DRIVE_RAM)
{
wsprintf((LPSTR)szBuf, "%ld",(DWORD)bs -> bsHiddenSecs);
SetDlgItemText(hDlg,iParameter++,szBuf);
wsprintf((LPSTR)szBuf, "%ld",(DWORD)bs -> bsHugeSectoes);
SetDlgItemText(hDlg,iParameter++,szBuf);
wsprintf((LPSTR)szBuf, "%#x",(BYTE)bs -> bsDriveNumber);
SetDlgItemText(hDlg,iParameter++,szBuf);
wsprintf((LPSTR)szBuf, "%d",(BYTE)bs -> bsReserved);
SetDlgItemText(hDlg,iParameter++,szBuf);
wsprintf((LPSTR)szBuf, "%#x",(BYTE)bs -> bsBootSig);
SetDlgItemText(hDlg,iParameter++,szBuf);
wsprintf((LPSTR)szBuf, "%lX",(DWORD)bs -> bsVolumeID); // serial number
SetDlgItemText(hDlg,iParameter++,szBuf);
// there are no NULL terminated strings
// so put the whole thing in a terminated
// string
memset(szBuf, NULL,64);
for (nCount=0; nCount < 11; nCount++)
szBuf[nCount] = bs -> bsVolumeLabel[nCount];
SetDlgItemText(hDlg,iParameter++,szBuf);
memset(szBuf, NULL,12);
for (nCount=0; nCount < 8 ; nCount++)
szBuf[nCount]=bs -> bsFileSysType[nCount];
SetDlgItemText(hDlg,iParameter++,szBuf);
}
else // its a RAMDRIVE
{
while (iParameter < ID_LAST)
SetDlgItemText(hDlg, iParameter++, "N/A");
}
}
/****************************************************************************
FUNCTION:
IsCDROM(int iDrive)
PURPOSE:
Determines if iDrive is a CD-ROM drive
****************************************************************************/
#pragma optimize("",off)
BOOL IsCDRomDrive(int iDrive)
{
BOOL bRet;
_asm
{
mov ax,1500h ; first test for presence of MSCDEX
xor bx,bx
int 2fh
mov ax,bx ; MSCDEX is not there if BX is still zero
or ax,ax ; ...so return FALSE from this function
jz no_mscdex
mov ax, 150bh ; MSCDEX driver check API
mov cx, iDrive ; ...cx is drive index
int 2fh ; will return AX=0 iff drive is not CDROM
mov bRet, ax
}
return bRet;
no_mscdex:
return FALSE;
}
#pragma optimize("",on)
/****************************************************************************
FUNCTION: GetPictRect(HWND hWnd, LPRECT lpRect)
PURPOSE: gets the rectangle to display the drive icon
****************************************************************************/
void GetPictRect(HWND hWnd, LPRECT lpRect)
{
GetWindowRect(GetDlgItem(hWnd,IDC_DRIVE), lpRect);
ScreenToClient(hWnd, (LPPOINT)lpRect);
ScreenToClient(hWnd, ((LPPOINT)lpRect)+1);
lpRect -> left = lpRect -> right + 5;
lpRect -> right += BM_WIDTH;
}
/****************************************************************************
FUNCTION: IsNetDrive(int iDrive)
PURPOSE: Determines if iDrive is a network drive
****************************************************************************/
WORD IsNetDrive(int iDrive)
{
int err;
char szDrive[3];
char szConn[64];
int nSize = 64;
szDrive[0] = (char)(iDrive+'A');
szDrive[1] = ':';
szDrive[2] = (char)0;
if (IsCDRomDrive(iDrive))
return 0;
err = WNetGetConnection(szDrive, szConn, &nSize);
if (err == WN_SUCCESS)
return 1;
if (err == WN_CONNECTION_CLOSED || err == WN_DEVICE_ERROR)
return 2;
return 0;
}
/****************************************************************************
FUNCTION: SetAllLabels(HWND hDlg, LPSTR szText)
PURPOSE: Sets all labels in hDlg to szText
****************************************************************************/
void SetAllLabels(HWND hDlg, LPSTR szText)
{
int i;
for (i=ID_FIRST; i < ID_LAST; i++)
SetDlgItemText(hDlg, i, szText);
}
/****************************************************************************
FUNCTION:
NewEditProc(HWND hEdit, UINT message, WPARAM wParam , LPARAM lParam)
PURPOSE:
The subclassed edit procedure. Restricts input of theedit control
to capital letters, the TAB key, and the backspace key.
****************************************************************************/
long FAR PASCAL __export NewEditProc(HWND hEdit, UINT message, WPARAM wParam , LPARAM lParam)
{
if (message == WM_CHAR)
{
// if it is a lower case letter, convert it to
// uppercase - NOTE: This is NOT portable!
if (wParam <= 'z' && wParam >= 'a')
wParam -= 'a' - 'A';
// allow only letters, TAB, or backspance keys
if ((wParam <= 'Z' && wParam >= 'A') || (wParam == VK_TAB) || (wParam == VK_BACK))
{
CallWindowProc(lpfnOldEditProc, hEdit, message, wParam, lParam);
//we never want more than one character in the
//control, so after we put the char in there,
// highlight it
SendMessage(hEdit, EM_SETSEL,0,MAKELPARAM(0,-1));
return 0;
}
else
{
MessageBeep(0);
return 0L;
}
}
CallWindowProc(lpfnOldEditProc, hEdit, message, wParam, lParam);
}
/****************************************************************************
FUNCTION: AboutDlgProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
****************************************************************************/
BOOL FAR PASCAL __export AboutDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK)
{
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
/****************************************************************************
FUNCTION: MyGetDriveType(BOOTSECTOR *bs)
PURPOSE: Given a pointer to a bootsector, determine what kind of drive
it is.
Drive Test
----- ----
RAM TRUE if only 1 FAT
FIXED TRUE if media descriptor is 0xF8h
FLOPPY Default
call IsCDRom() and IsNetDrive() before calling this function!
(or integrate them into it...)
****************************************************************************/
int MyGetDriveType(BOOTSECTOR *bs)
{
if (bs -> bsFAT == 1)
return DRIVE_RAM;
if (bs -> bsMedia == 0xF8)
return DRIVE_FIXED;
return DRIVE_REMOVABLE;
}